package com.dt.platform.oa.service.impl;

import javax.annotation.Resource;

import com.dt.platform.constants.enums.common.CodeModuleEnum;
import com.dt.platform.constants.enums.oa.ProjectStatusEnum;
import com.dt.platform.constants.enums.oa.ProjectUserRoleEnum;
import com.dt.platform.constants.enums.oa.ProjectUserStatusEnum;
import com.dt.platform.domain.oa.*;
import com.dt.platform.oa.service.IProjectRcdService;
import com.dt.platform.oa.service.IProjectUserService;
import com.dt.platform.proxy.common.CodeModuleServiceProxy;
import com.github.foxnic.commons.lang.StringUtil;
import com.github.foxnic.dao.data.Rcd;
import com.github.foxnic.dao.data.RcdSet;
import org.github.foxnic.web.session.SessionUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.github.foxnic.dao.entity.ReferCause;
import com.github.foxnic.commons.collection.MapUtil;
import java.util.Arrays;


import java.util.List;
import com.github.foxnic.api.transter.Result;
import com.github.foxnic.dao.data.PagedList;
import com.github.foxnic.dao.entity.SuperService;
import com.github.foxnic.dao.spec.DAO;
import java.lang.reflect.Field;
import com.github.foxnic.commons.busi.id.IDGenerator;
import com.github.foxnic.sql.expr.ConditionExpr;
import com.github.foxnic.api.error.ErrorDesc;
import com.github.foxnic.dao.excel.ExcelWriter;
import com.github.foxnic.dao.excel.ValidateResult;
import com.github.foxnic.dao.excel.ExcelStructure;
import java.io.InputStream;
import com.github.foxnic.sql.meta.DBField;
import com.github.foxnic.dao.data.SaveMode;
import com.github.foxnic.dao.meta.DBColumnMeta;
import com.github.foxnic.sql.expr.Select;
import java.util.ArrayList;
import com.dt.platform.oa.service.IProjectService;
import org.github.foxnic.web.framework.dao.DBConfigs;
import java.util.Date;
import java.util.Map;

/**
 * <p>
 * 项目管理服务实现
 * </p>
 * @author 金杰 , maillank@qq.com
 * @since 2025-06-19 21:01:03
*/


@Service("OaProjectService")

public class ProjectServiceImpl extends SuperService<Project> implements IProjectService {

	@Autowired
	private IProjectRcdService projectRcdService;

	@Autowired
	private IProjectUserService projectUserService;

	/**
	 * 注入DAO对象
	 * */
	@Resource(name=DBConfigs.PRIMARY_DAO) 
	private DAO dao=null;

	/**
	 * 获得 DAO 对象
	 * */
	public DAO dao() { return dao; }



	@Override
	public Object generateId(Field field) {
		return IDGenerator.getSnowflakeIdString();
	}

	/**
	 * 添加，根据 throwsException 参数抛出异常或返回 Result 对象
	 *
	 * @param project  数据对象
	 * @param throwsException 是否抛出异常，如果不抛出异常，则返回一个失败的 Result 对象
	 * @return 结果 , 如果失败返回 false，成功返回 true
	 */
	@Override
	public Result insert(Project project,boolean throwsException) {

		if(dao.queryRecord("select count(1) cnt from oa_project_phase where project_id=?",project.getSelectedCode()).getInteger("cnt")==0){
			return ErrorDesc.failureMessage("请至少需要一个项目阶段");
		}
//		List<String> strList=project.getPartUserStrList();
//
//		if(strList==null||strList.size()==0){
//			return ErrorDesc.failureMessage("请至少需要一个项目阶段");
//		}


		if(StringUtil.isBlank(project.getOwnerId())){
			project.setOwnerId(SessionUser.getCurrent().getActivatedEmployeeId());
		}

		if(StringUtil.isBlank(project.getProjectStatus())){
			project.setProjectStatus(ProjectStatusEnum.WAIT.code());
		}

		if(StringUtil.isBlank(project.getCode())){
			project.setProjectStatus(ProjectStatusEnum.WAIT.code());
		}

		if(StringUtil.isBlank(project.getCode())){
			Result codeResult= CodeModuleServiceProxy.api().generateCode(CodeModuleEnum.COMMON_CODE.code());
			if(!codeResult.isSuccess()){
				return codeResult;
			}else{
				project.setCode(codeResult.getData().toString());
			}
		}

		Result r=super.insert(project,throwsException);
		String cUserId=SessionUser.getCurrent().getActivatedEmployeeId();
		if(r.isSuccess()){
			dao.execute("update oa_project_phase set project_id=? where project_id=?",project.getId(),project.getSelectedCode());
			boolean userMatchIt=false;
			boolean leaderMatchIt=false;

			List<String> strList=project.getPartUserStrList();
			if(strList!=null&&strList.size()>0){
				List<ProjectUser> userList=new ArrayList<>();
				for(int i=0;i<strList.size();i++){
					String userId=strList.get(i);
					if(StringUtil.isBlank(userId)){
						continue;
					}
					ProjectUserVO userQuery=new ProjectUserVO();
					userQuery.setUserId(strList.get(i));
					userQuery.setProjectId(project.getId());
					ProjectUser sourceUser=projectUserService.queryEntity(userQuery);

					ProjectUser user=new ProjectUser();
					user.setOwnType("project");
					user.setUserId(strList.get(i));
					user.setRole(ProjectUserRoleEnum.MEMBER.code());
					user.setProjectId(project.getId());
					user.setCallMethod("direct");

					if(cUserId.equals(strList.get(i))){
						userMatchIt=true;
					}

					if(project.getLeaderId().equals(strList.get(i))){
						leaderMatchIt=true;
						user.setRole(ProjectUserRoleEnum.LEADER.code());
					}

					if(sourceUser==null){
						user.setInTime(new Date());
						user.setStatus(ProjectUserStatusEnum.IN.code());
					}else{
						user.setStatus(sourceUser.getStatus());
						user.setInTime(sourceUser.getInTime());
						user.setOutTime(new Date());
					}
					userList.add(user);
				}
				if(userList.size()>0){
					projectUserService.insertList(userList);
				}
			}

			if(!userMatchIt){
				//首次新建时，创建人同时为协作人。
				ProjectUser user=new ProjectUser();
				user.setOwnType("project");
				user.setUserId(cUserId);
				user.setProjectId(project.getId());
				user.setStatus("in");
				user.setRole(ProjectUserRoleEnum.MEMBER.code());
				user.setInTime(new Date());
				user.setCallMethod("direct");
				projectUserService.insert(user,false);
			}

			if(!leaderMatchIt){
				ProjectUser user=new ProjectUser();
				user.setOwnType("project");
				user.setUserId(project.getLeaderId());
				user.setProjectId(project.getId());
				user.setStatus("in");
				user.setRole(ProjectUserRoleEnum.LEADER.code());
				user.setInTime(new Date());
				user.setCallMethod("direct");
				projectUserService.insert(user,false);
			}
			this.resetProjectUser(project.getId());
		}
		return r;
	}


	public Result resetProjectUser(String id){
		String sql="select * from oa_project_user where own_type='phase' and deleted=0 and project_id=?\n" +
				"and id not in (select id from oa_project_user where own_type='project' and deleted=0 and project_id=?)";
		RcdSet rs=dao.query(sql,id,id);
		for(int i=0;i<rs.size();i++){
			ProjectUser user=new ProjectUser();
			user.setOwnType("project");
			user.setUserId(rs.getRcd(i).getString("id"));
			user.setProjectId(id);
			user.setStatus("in");
			user.setRole(ProjectUserRoleEnum.MEMBER.code());
			user.setInTime(new Date());
			projectUserService.insert(user,false);
		}
		return ErrorDesc.success();
	}


	String userInProjectSql="select 'project' range_type,leader_id user_id,'leader' join_type, id owner_source,id project_id from oa_project where deleted=0 and id=? and leader_id is not null and leader_id<>''\n" +
			"union all\n" +
			"select 'project' range_type,user_id,'member' join_type, id owner_source,project_id project_id from oa_project_user where project_id=? and deleted=0 and status='in' and own_type='project' and user_id is not null and user_id<>''\n" +
			"union all\n" +
			"select 'task' range_type,leader_id,'leader' join_type,id owner_source,project_id project_id from oa_project_task where deleted=0 and project_id=? and leader_id is not null and leader_id<>''\n" +
			"union all\n" +
			"select 'task' range_type,b.user_id,'member' join_type,a.id owner_source,a.project_id project_id from oa_project_task a,oa_project_user b where a.id=b.project_id and a.deleted=0 and a.project_id=? and b.user_id is not null and b.user_id<>''\n" +
			"union all\n" +
			"select 'phase' range_type,leader_id,'leader' join_type,id owner_source ,project_id project_id from oa_project_phase where deleted=0 and project_id=? and leader_id is not null and leader_id<>''\n" +
			"union all\n" +
			"select 'phase' range_type,b.user_id,'member' join_type,a.id owner_source,a.project_id project_id from oa_project_phase a,oa_project_user b where a.id=b.project_id and a.deleted=0 and a.project_id=? and b.user_id is not null and b.user_id<>''";
	@Override
	public Boolean userInProjectRangeAll(String userId,String projectId) {
		Rcd rs=dao.queryRecord("select 1 from ("+userInProjectSql+") tab where user_id=?",projectId,projectId,projectId,projectId,projectId,projectId,userId);
		if(rs==null){
			return false;
		}
		return true;
	}

	@Override
	public Boolean userInProject(String userId,String projectId) {
		Rcd rs=dao.queryRecord("select 1 from ("+userInProjectSql+") tab where range_type='project' and user_id=?",projectId,projectId,projectId,projectId,projectId,projectId,userId);
		if(rs==null){
			return false;
		}
		return true;
	}

	@Override
	public Boolean userInProjectTask(String userId, String taskId) {
		Rcd taskRs=dao.queryRecord("select * from oa_project_task where id=?",taskId);
		if(taskRs==null){
			return false;
		}
		String projectId=taskRs.getString("project_id");
		Rcd rs=dao.queryRecord("select 1 from ("+userInProjectSql+") tab where range_type='task' and user_id=? and owner_source=?",projectId,projectId,projectId,projectId,projectId,projectId,userId,taskId);
		if(rs==null){
			return false;
		}
		return true;
	}



	@Override
	public Boolean userInProjectLeader(String userId,String projectId) {
		Rcd rs=dao.queryRecord("select 1 from ("+userInProjectSql+") tab where join_type='leader' and range_type='project' and user_id=?",projectId,projectId,projectId,projectId,projectId,projectId,userId);
		if(rs==null){
			return false;
		}
		return true;
	}


	@Override
	public Boolean userInProjectTaskLeader(String userId, String taskId) {

		Rcd taskRs=dao.queryRecord("select * from oa_project_task where id=?",taskId);
		if(taskRs==null){
			return false;
		}
		String projectId=taskRs.getString("project_id");
		Rcd rs=dao.queryRecord("select 1 from ("+userInProjectSql+") tab where join_type='leader' and range_type='task' and user_id=? and owner_source=?",projectId,projectId,projectId,projectId,projectId,projectId,userId,taskId);
		if(rs==null){
			return false;
		}
		return true;
	}


	@Override
	public Boolean userInProjectPhase(String userId, String phaseId) {
		return null;
	}

	@Override
	public Boolean userInProjectPhaseLeader(String userId, String phaseId) {
		Rcd taskRs=dao.queryRecord("select * from oa_project_phase where id=?",phaseId);
		if(taskRs==null){
			return false;
		}
		String projectId=taskRs.getString("project_id");
		Rcd rs=dao.queryRecord("select 1 from ("+userInProjectSql+") tab where join_type='leader' and range_type='phase' and user_id=? and owner_source=?",projectId,projectId,projectId,projectId,projectId,projectId,userId,phaseId);
		if(rs==null){
			return false;
		}
		return true;
	}


	@Override
	public Result action(String id, String action,String ct) {
		String cUserId=SessionUser.getCurrent().getActivatedEmployeeId();
		Project project=this.getById(id);
		if("close".equals(action)){
			if(!this.userInProjectLeader(cUserId,id)){
				return ErrorDesc.failureMessage("只有项目经理才能关闭");
			}
			ProjectRcd rcd=new ProjectRcd();
			rcd.setRcdTime(new Date());
			rcd.setOwnerType("project");
			rcd.setOwnerId(id);
			rcd.setUserId(cUserId);
			rcd.setContent(SessionUser.getCurrent().getRealName()+"关闭了项目");
			projectRcdService.insert(rcd,false);


			dao.execute("update oa_project set project_status=? where id=?",ProjectStatusEnum.CLOSE.code(),id);
		}

		if("open".equals(action)){
			if(!this.userInProjectLeader(cUserId,id)){
				return ErrorDesc.failureMessage("只有项目经理才能打开");
			}
			project.setProjectStatus(ProjectStatusEnum.ACTING.code());
			//判断所在阶段
			Rcd rs=dao.queryRecord("select 1 from oa_project_phase where deleted=0 and id=?",project.getCurPhase());
			if(rs==null){
				//配置一个阶段，默认第一个阶段
				Rcd rs1=dao.queryRecord("select * from oa_project_phase where deleted=0 and rk=1 and project_id=?",id);
				if(rs1!=null){
					dao.execute("update oa_project set cur_phase=? where id=?",rs1.getString("id"),id);
					ProjectRcd rcd=new ProjectRcd();
					rcd.setRcdTime(new Date());
					rcd.setOwnerType("phase");
					rcd.setOwnerId(id);
					rcd.setUserId(cUserId);
					rcd.setContent(SessionUser.getCurrent().getRealName()+"项目启动，初始化阶段【"+rs1.getString("name")+"】。");
					projectRcdService.insert(rcd,false);
				}
			}
			ProjectRcd rcd=new ProjectRcd();
			rcd.setRcdTime(new Date());
			rcd.setOwnerType("project");
			rcd.setOwnerId(id);
			rcd.setUserId(cUserId);
			rcd.setContent(SessionUser.getCurrent().getRealName()+"打开了项目");
			projectRcdService.insert(rcd,false);
			dao.execute("update oa_project set project_status=? where id=?",ProjectStatusEnum.ACTING.code(),id);
		}
		return ErrorDesc.success();
	}

	/**
	 * 添加，如果语句错误，则抛出异常
	 * @param project 数据对象
	 * @return 插入是否成功
	 * */
	@Override
	public Result insert(Project project) {
		return this.insert(project,true);
	}

	/**
	 * 批量插入实体，事务内
	 * @param projectList 实体数据清单
	 * @return 插入是否成功
	 * */
	@Override
	public Result insertList(List<Project> projectList) {
		return super.insertList(projectList);
	}

	
	/**
	 * 按主键删除项目管理
	 *
	 * @param id 主键
	 * @return 删除是否成功
	 */
	public Result deleteByIdPhysical(String id) {
		String cUserId=SessionUser.getCurrent().getActivatedEmployeeId();
		if(!this.userInProjectLeader(cUserId,id)){
			return ErrorDesc.failureMessage("只有项目经理才能进行删除");
		}
		Project project = new Project();
		if(id==null) return ErrorDesc.failure().message("id 不允许为 null 。");
		project.setId(id);
		try {
			boolean suc = dao.deleteEntity(project);
			return suc?ErrorDesc.success():ErrorDesc.failure();
		}
		catch(Exception e) {
			Result r= ErrorDesc.failure();
			r.extra().setException(e);
			return r;
		}
	}
	
	/**
	 * 按主键删除项目管理
	 *
	 * @param id 主键
	 * @return 删除是否成功
	 */
	public Result deleteByIdLogical(String id) {
		String cUserId=SessionUser.getCurrent().getActivatedEmployeeId();
		if(!this.userInProjectLeader(cUserId,id)){
			return ErrorDesc.failureMessage("只有项目经理才能进行删除");
		}

		Project project = new Project();
		if(id==null) return ErrorDesc.failure().message("id 不允许为 null 。");
		project.setId(id);
		project.setDeleted(true);
		project.setDeleteBy((String)dao.getDBTreaty().getLoginUserId());
		project.setDeleteTime(new Date());
		try {
			boolean suc = dao.updateEntity(project,SaveMode.NOT_NULL_FIELDS);
			return suc?ErrorDesc.success():ErrorDesc.failure();
		}
		catch(Exception e) {
			Result r= ErrorDesc.failure();
			r.extra().setException(e);
			return r;
		}
	}

	/**
	 * 更新，如果执行错误，则抛出异常
	 * @param project 数据对象
	 * @param mode 保存模式
	 * @return 保存是否成功
	 * */
	@Override
	public Result update(Project project , SaveMode mode) {
		return this.update(project,mode,true);
	}

	/**
	 * 更新，根据 throwsException 参数抛出异常或返回 Result 对象
	 * @param project 数据对象
	 * @param mode 保存模式
	 * @param throwsException 是否抛出异常，如果不抛出异常，则返回一个失败的 Result 对象
	 * @return 保存是否成功
	 * */
	@Override
	public Result update(Project project , SaveMode mode,boolean throwsException) {


		Project before=this.getById(project.getId());
		Result r=super.update(project , mode , throwsException);

		if(r.isSuccess()){
			Project after=this.getById(project.getId());
			//更换leader
			if(!before.getLeaderId().equals(after.getLeaderId())){
				Rcd rs=dao.queryRecord("select * from oa_project_user where own_type='project' and deleted=0 and project_id=? and user_id=?",project.getId(),after.getLeaderId());
				if(rs==null){
					//用户不存在，添加
					dao.execute("update oa_project_user set role='member' where own_type='project' and deleted=0 and project_id=?",before.getId());
					ProjectUser user=new ProjectUser();
					user.setOwnType("project");
					user.setUserId(after.getLeaderId());
					user.setProjectId(project.getId());
					user.setStatus("in");
					user.setCallMethod("direct");
					user.setRole(ProjectUserRoleEnum.LEADER.code());
					user.setInTime(new Date());
					projectUserService.insert(user,false);

				}else{
					dao.execute("update oa_project_user set role='member' where own_type='project' and deleted=0 and project_id=?",before.getId());
				}
			}
			dao.execute("update oa_project_user set role='leader' where own_type='project' and deleted=0 and project_id=? and user_id=?",after.getId(),after.getLeaderId());
			this.resetProjectUser(project.getId());
		}
		return r;
	}

	/**
	 * 更新实体集，事务内
	 * @param projectList 数据对象列表
	 * @param mode 保存模式
	 * @return 保存是否成功
	 * */
	@Override
	public Result updateList(List<Project> projectList , SaveMode mode) {
		return super.updateList(projectList , mode);
	}

	
	/**
	 * 按主键更新项目管理
	 *
	 * @param id 主键
	 * @return 是否更新成功
	 */
	public boolean update(DBField field,Object value , String id) {
		if(id==null) throw new IllegalArgumentException("id 不允许为 null ");
		if(!field.table().name().equals(this.table())) throw new IllegalArgumentException("更新的数据表["+field.table().name()+"]与服务对应的数据表["+this.table()+"]不一致");
		int suc=dao.update(field.table().name()).set(field.name(), value).where().and("id = ? ",id).top().execute();
		return suc>0;
	}

	
	/**
	 * 按主键获取项目管理
	 *
	 * @param id 主键
	 * @return Project 数据对象
	 */
	public Project getById(String id) {
		Project sample = new Project();
		if(id==null) throw new IllegalArgumentException("id 不允许为 null ");
		sample.setId(id);
		return dao.queryEntity(sample);
	}

	/**
	 * 等价于 queryListByIds
	 * */
	@Override
	public List<Project> getByIds(List<String> ids) {
		return this.queryListByIds(ids);
	}

	@Override
	public List<Project> queryListByIds(List<String> ids) {
		return super.queryListByUKeys("id",ids);
	}

	@Override
	public Map<String, Project> queryMapByIds(List<String> ids) {
		return super.queryMapByUKeys("id",ids, Project::getId);
	}



	/**
	 * 查询实体集合，默认情况下，字符串使用模糊匹配，非字符串使用精确匹配
	 *
	 * @param sample  查询条件
	 * @return 查询结果
	 * */
	@Override
	public List<Project> queryList(ProjectVO sample) {
		return super.queryList(sample);
	}


	/**
	 * 分页查询实体集，字符串使用模糊匹配，非字符串使用精确匹配
	 *
	 * @param sample  查询条件
	 * @param pageSize 分页条数
	 * @param pageIndex 页码
	 * @return 查询结果
	 * */
	@Override
	public PagedList<Project> queryPagedList(ProjectVO sample, int pageSize, int pageIndex) {
		return super.queryPagedList(sample, pageSize, pageIndex);
	}

	/**
	 * 分页查询实体集，字符串使用模糊匹配，非字符串使用精确匹配
	 *
	 * @param sample  查询条件
	 * @param condition 其它条件
	 * @param pageSize 分页条数
	 * @param pageIndex 页码
	 * @return 查询结果
	 * */
	@Override
	public PagedList<Project> queryPagedList(Project sample, ConditionExpr condition, int pageSize, int pageIndex) {
		return super.queryPagedList(sample, condition, pageSize, pageIndex);
	}

	/**
	 * 检查 实体 是否已经存在 , 判断 主键值不同，但指定字段的值相同的记录是否存在
	 *
	 * @param project 数据对象
	 * @return 判断结果
	 */
	public Boolean checkExists(Project project) {
		//TDOD 此处添加判断段的代码
		//boolean exists=super.checkExists(project, SYS_ROLE.NAME);
		//return exists;
		return false;
	}

	/**
	 * 批量检查引用
	 * @param ids  检查这些ID是否又被外部表引用
	 * */
	@Override
	public <T> Map<T, ReferCause> hasRefers(List<T> ids) {
		// 默认无业务逻辑，返回此行；有业务逻辑需要校验时，请修改并使用已注释的行代码！！！
		return MapUtil.asMap(ids,new ReferCause(false));
		// return super.hasRefers(FoxnicWeb.BPM_PROCESS_INSTANCE.FORM_DEFINITION_ID,ids);
	}





}